// ==UserScript== // @name ChatGPT宽屏模式 // @namespace https://greasyfork.org/ // @version 1.2.1 // @description 将页面宽度展开 // @author Await // @match https://chat.openai.com/ // @match https://chat.openai.com/c/* // @match https://chat.openai.com/?* // @match https://poe.com/ // @match https://poe.com/chat/?* // @license MIT // ==/UserScript== (function () { "use strict"; const attributeKey = "await-attribute"; const cacheOpenStateKey = "await-cache-open-state"; const cacheCloseStateKey = "await-cache-close-state"; const btnId = "await-btn"; const styleId = "await-max-width"; const btnShowTipId = "await-show-tip"; const cacheKey = "await-cache"; const newMaxWidth = "90rem"; const desiredMinWidth = 1280; const maxCount = 10; const targetClassName = ".xl\\:max-w-3xl"; const targetClass = "flex flex-col text-sm dark:bg-gray-800"; const cacheTheme = "theme"; const themeDark = "dark"; const themeLight = "light"; const bodyClass = "antialiased"; const growClass = "grow"; // !(function () { // try { // var d = document.documentElement, // c = d.classList; // c.remove("light", "dark"); // console.log("system", c); // var e = localStorage.getItem("theme"); // if ("system" === e || (!e && true)) { // var t = "(prefers-color-scheme: dark)", // m = window.matchMedia(t); // if (m.media !== t || m.matches) { // console.log("1"); // d.style.colorScheme = "dark"; // c.add("dark"); // } else { // console.log("2"); // d.style.colorScheme = "light"; // c.add("light"); // } // } else if (e) { // console.log("3"); // c.add(e || ""); // } // if (e === "light" || e === "dark") d.style.colorScheme = e; // } catch (e) {} // })(); function setCache(key, value) { localStorage.setItem(key, value); } function getCache(key) { return localStorage.getItem(key); } function getByClass(className) { const func = function (name) { return document.getElementsByClassName(name); }; return gets(func, className); } function getQuery(name) { const func = function (name) { return document.querySelector(name); }; return gets(func, name); } function getById(id) { const func = function (id) { return document.getElementById(id); }; return gets(func, id); } function gets(fun, name, count = 0) { const btn = fun(name); if (!btn) { if (count > maxCount) { return null; //防止死循环 } setTimeout(function () { return gets(fun, name, count + 1); }, 1000); } return btn; } function styleCreate() { const style = document.createElement("style"); style.innerHTML = ` .${styleId} { max-width: ${newMaxWidth} !important; } `; document.head.appendChild(style); } function bodyClassFunc() { const body = getByClass(bodyClass)[0]; if (!body) { return; } const observer = new MutationObserver((mutationsList, observer) => { for (const mutation of mutationsList) { if ( mutation.type === "attributes" && mutation.attributeName === "style" ) { const newStyle = body.getAttribute("style"); if (!newStyle) { btnClickAdd(true); btnClick(true); } } } }); const config = { attributes: true, attributeFilter: ["style"] }; observer.observe(body, config); } function btnClickAdd(tt = false) { //只包含这个growClass的class的元素 const promptTextarea = getQuery(`.${growClass}:not([class*=' '])`); if (!promptTextarea) { if (!tt) { return; } else { setTimeout(function () { btnClickAdd(tt); }, 1000); return; } } if (!promptTextarea.hasAttribute(attributeKey)) { promptTextarea.insertAdjacentHTML( "afterend", // `
` `
` ); promptTextarea.insertAdjacentHTML( "afterend", // `
` `
` ); themeAdd(); btnTextUpdate(); run(); promptTextarea.setAttribute(attributeKey, true); } else { if (tt) { setTimeout(function () { btnClickAdd(tt); }, 1000); } } } function removeStyle(el) { el.style.transition = "max-width 1s"; setTimeout(function () { el.style.transition = ""; }, 1000); el.classList.remove(styleId); } function editStyle(el) { el.style.transition = "max-width 1s"; setTimeout(function () { el.style.transition = ""; }, 1000); el.classList.add(styleId); } function btnTextUpdate() { const cache2 = getCache(cacheKey); const btn = getById(btnId); btn.innerHTML = ""; if (cache2 === cacheOpenStateKey) { btn.insertAdjacentHTML( "afterbegin", `
还原
` // `
// // // 还原
` // `还原` // `撑开` ); } else { btn.insertAdjacentHTML( "afterbegin", `
撑开
` // `撑开` ); } btnTypeEdit(btn); } function btnTypeEdit(el) { if (el && !el.hasAttribute(attributeKey)) { el.addEventListener("click", function () { setCache( cacheKey, getCache(cacheKey) === cacheOpenStateKey ? cacheCloseStateKey : cacheOpenStateKey ); run(); btnTextUpdate(); }); el.setAttribute(attributeKey, true); } } function themeAdd() { const cache = getCache(cacheTheme); const el = getById(btnId + "-" + cacheTheme); el.innerHTML = ""; if (cache !== themeLight) { el.insertAdjacentHTML( "afterbegin", `
🌞
` // `
🌞
` ); } else { el.insertAdjacentHTML( "afterbegin", `
🌙
` ); } textInformation(el); textInformation( getById(btnId + "-" + cache === themeDark ? themeDark : themeLight) ); } function textInformation(el) { if (el && !el.hasAttribute(attributeKey)) { el.addEventListener("click", function () { const cache = getCache(cacheTheme); //修改html中的style跟class const html = getQuery("html"); const currentTheme = cache !== themeLight ? themeLight : themeDark; html.className = ""; html.className = currentTheme; html.style.colorScheme = currentTheme; setCache(cacheTheme, currentTheme); themeAdd(); }); el.setAttribute(attributeKey, true); } } function checkCache() { const cache = getCache(cacheKey); if (!cache) { setCache(cacheKey, true); } } function setStyle(cache, el) { if (cache === cacheOpenStateKey) { editStyle(el); } else { removeStyle(el); } } function getNav(count = 0) { const nav = document.querySelector("nav"); if (!nav) { if (count > maxCount) { return null; } setTimeout(function () { return getNav(count); }, 1000); } return nav; } function showTip() { const toggleButton = getNav(); if (!toggleButton) { return; } toggleButton.insertAdjacentHTML( "beforeend", `
如果页面宽度未展开,请重新点击此树结构导航栏
或者直接点击我
提示内容十秒后自动消失
` ); const btn = getById(btnShowTipId); if (!btn.hasAttribute(attributeKey)) { btn.addEventListener("click", function () { runAll(); }); setTimeout(function () { btn.remove(); }, 10000); btn.setAttribute(attributeKey, true); } } function btnClick(tt = false) { const toggleButton = getNav(); if (!toggleButton) { if (!tt) return; else { setTimeout(function () { btnClick(tt); }, 1000); return; } } if (!toggleButton.hasAttribute(attributeKey)) { toggleButton.addEventListener("click", function () { setTimeout(function () { runAll(); btnClick(); }, 1000); }); toggleButton.setAttribute(attributeKey, true); } else { if (tt) { setTimeout(function () { btnClick(tt); }, 1000); } } } function checkForm() { var elementForm = document.querySelectorAll("form"); if (!elementForm || elementForm.length === 0) { setTimeout(function () { checkObserver(); }, 1000); return; } const cache = getCache(cacheKey); elementForm.forEach(function (element) { if (element.className.indexOf("xl:max-w-3xl") > -1) { setStyle(cache, element); } }); } function checkObserver() { var parentElement = document.getElementsByClassName(targetClass)[0]; if (!parentElement) { setTimeout(function () { checkObserver(); }, 1000); return; } const cache = getCache(cacheKey); parentElement.querySelectorAll(targetClassName).forEach(function (flexDiv) { setStyle(cache, flexDiv); }); var observer = new MutationObserver((mutations) => { mutations.forEach(function (mutation) { if (!document.contains(parentElement)) { observer.disconnect(); return; } mutation.addedNodes.forEach(function (addedNode) { if (addedNode instanceof Document || addedNode instanceof Element) { var flexDivList = addedNode.querySelectorAll(targetClassName); flexDivList.forEach(function (flexDiv) { setStyle(cache, flexDiv); }); } }); }); }); var config = { childList: true, subtree: true }; observer.observe(document.body, config); } function runAll() { btnClickAdd(); themeAdd(); } function run() { checkForm(); checkObserver(); } window.addEventListener("resize", runAll); window.onload = function () { if (window.innerWidth < desiredMinWidth) { return; } checkCache(); bodyClassFunc(); styleCreate(); showTip(); btnClick(); setTimeout(function () { runAll(); }, 2000); }; })();